package geppetto.cat.programs;


import geppetto.cat.alignments.AlignmentEvaluator;
import geppetto.cat.alignments.AlignmentStats;
import geppetto.cat.alignments.AlignmentSymetrization;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.alignments.AlignmentEvaluator.Evaluation;
import geppetto.cat.corpus.BilingualCorpus;
import geppetto.cat.models.AbstractModel;

import java.io.IOException;



public class EvaluateAgainstM4Recall {
	
	String corpusName;
	String corpusDescription;
	String modelName;
	BilingualCorpus forwardCorpus, backwardCorpus;
	String forwardModelDir, backwardModelDir;
	double epsilon, slack;
	int maxStep, maxProjectIter;
	boolean projectTestTime;
	double[] HANSARDS_M4P_F = {0.6631, 0.6711, 0.6804, 0.6945, 0.7283, 0.7659, 0.7883, 0.8074, 0.8244, 0.8439};
	double[] HANSARDS_M4R_F = {0.775, 0.7922, 0.8139, 0.8326, 0.876, 0.9055, 0.9207, 0.9239, 0.934, 0.9433};
	double[] HANSARDS_M4P_B={0.7257, 0.7159, 0.7204, 0.7199, 0.7401, 0.7811, 0.8013, 0.8125, 0.8374, 0.8489};
	double[] HANSARDS_M4R_B={0.7996, 0.8177, 0.8226, 0.8401, 0.8563, 0.8903, 0.9013, 0.9068, 0.9301, 0.932};
//	double[] EPPS_M4P_F={0.6202,0.6362,0.6748,0.7051,0.7259,0.765,0.7811,0.8109,0.8283,0.8427};
//	double[] EPPS_M4R_F={0.5608,0.5737,0.6108,0.6333,0.6515,0.6855,0.7016,0.7247,0.7385,0.7511};
//	double[] EPPS_M4P_B={0.7002,0.7149,0.7389,0.757,0.773,0.8005,0.8234,0.8448,0.866,0.8775};
//	double[] EPPS_M4R_B={0.6006,0.6134,0.6346,0.6482,0.6625,0.6903,0.7086,0.7247,0.7412,0.7496};
//	double[] EN_PT_M4P_F={0.5515,0.5639,0.5857,0.6353,0.6393,0.7303,0.7534,0.7613,0.7826,0.7979};
//	double[] EN_PT_M4R_F={0.6319,0.6638,0.6702,0.734,0.734,0.817,0.8234,0.8298,0.8553,0.8532};
//	double[] EN_PT_M4P_B={0.6547,0.6682,0.7017,0.7005,0.7382,0.7547,0.7871,0.8009,0.8407,0.8391};
//	double[] EN_PT_M4R_B={0.7021,0.7106,0.7468,0.7617,0.7957,0.8128,0.8234,0.8383,0.8787,0.8745};

//	double[] HANSARDS_M4P_F = {0.8439};
//	double[] HANSARDS_M4R_F = {0.9433};
//	double[] HANSARDS_M4P_B={0.8489};
//	double[] HANSARDS_M4R_B={0.932};
	double[] EPPS_M4P_F={0.8427};
	double[] EPPS_M4R_F={0.7511};
	double[] EPPS_M4P_B={0.8775};
	double[] EPPS_M4R_B={0.7496};
	double[] EN_PT_M4P_F={0.7979};
	double[] EN_PT_M4R_F={0.8532};
	double[] EN_PT_M4P_B={0.8391};
	double[] EN_PT_M4R_B={0.8745};
	double[] PT_ES_M4P_F={0.8795};
	double[] PT_ES_M4R_F={0.9367};
	double[] PT_ES_M4P_B={0.8456};
	double[] PT_ES_M4R_B={0.9098};
	double[] PT_FR_M4P_F={0.8501};
	double[] PT_FR_M4R_F={0.8201};
	double[] PT_FR_M4P_B={0.8452};
	double[] PT_FR_M4R_B={0.7713};
	double[] ES_FR_M4P_F={0.8525};
	double[] ES_FR_M4R_F={0.7841};
	double[] ES_FR_M4P_B={0.8837};
	double[] ES_FR_M4R_B={0.7841};
	
	public EvaluateAgainstM4Recall(String[] args) {
		corpusDescription = args[0];
		corpusName = args[1];
		forwardModelDir = args[2];
		backwardModelDir = args[3];
		modelName = args[4];
		projectTestTime = Boolean.parseBoolean(args[5]);
		epsilon = Double.parseDouble(args[6]);
		slack = Double.parseDouble(args[7]);
		maxStep = Integer.parseInt(args[8]);
		maxProjectIter = Integer.parseInt(args[9]);
		System.out.println("Corpus " + corpusDescription);
		System.out.println("ForwardModelDir " + forwardModelDir);
		System.out.println("BackwardModelDir " + backwardModelDir);
		System.out.println("Model Name " + modelName);
		System.out.println("ProjectAtTest Name " + projectTestTime);
		System.out.println("Epsilon " + epsilon);
		System.out.println("Slack " + slack);
		System.out.println("maxStep " +maxStep);
		System.out.println("maxProjectIter " +maxProjectIter);
		System.out.println("---");
	}
	
	public static void main(String[] args) throws IOException {
		EvaluateAgainstM4Recall exp = new EvaluateAgainstM4Recall(args);
		exp.run();
	}
	
	public void initializeCorpus(String corpusDesc, int size, int maxSentSize)
	throws IOException {
		System.out.println("Loading Corpus");
		forwardCorpus = BilingualCorpus.getCorpusFromFileDescription(
		corpusDesc, size, maxSentSize);
		backwardCorpus = forwardCorpus.reverse();
		
		System.out.println("Finished Loading Corpus");
}
	
	public void run() throws IOException {
		int[] sizes = {1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000};
	//	int[] sizes = {1000000};
		double[] forwardR = null;
		double[] backwardR = null;
		
		if(corpusName.equalsIgnoreCase("hansards")){
			forwardR = HANSARDS_M4R_F;
			backwardR = HANSARDS_M4R_B;
		}else if(corpusName.equalsIgnoreCase("epps")){
			forwardR = EPPS_M4R_F;
			backwardR = EPPS_M4R_B;
		}else if(corpusName.equalsIgnoreCase("en-pt")){
			forwardR = EN_PT_M4R_F;
			backwardR = EN_PT_M4R_B;
		}else if(corpusName.equalsIgnoreCase("pt-es")){
			forwardR = PT_ES_M4R_F;
			backwardR = PT_ES_M4R_B;
		}else if(corpusName.equalsIgnoreCase("pt-fr")){
			forwardR = PT_FR_M4R_F;
			backwardR = PT_FR_M4R_B;
		}else if(corpusName.equalsIgnoreCase("es-fr")){
			forwardR = ES_FR_M4R_F;
			backwardR = ES_FR_M4R_B;
		}else{
			System.out.println("Don't have M4 Values... Exiting");
			System.exit(-1);
		}
		
		String size, oldSize;
		oldSize = "1000000";
		for(int i = 0; i < sizes.length; i++){
			initializeCorpus(corpusDescription, sizes[i], 40);		
			//Hack
			size = ""+sizes[i];
			forwardModelDir = forwardModelDir.replace(oldSize, size);
			backwardModelDir = backwardModelDir.replace(oldSize, size);
			AbstractModel[] models = GenericMethods.initializeModelsFullDir(forwardCorpus, backwardCorpus, modelName, forwardModelDir,backwardModelDir, epsilon, slack, maxStep, maxProjectIter);
			AlignmentsSet align_uvf = null, align_uvb = null;
			float forwardThresh =
				models[0].tuneTreshholdPrecisionRecallFixOtherValue(BilingualCorpus.TEST_CORPUS, true, forwardR[i], 0.0005, projectTestTime);
			float backwardThresh =
				models[1].tuneTreshholdPrecisionRecallFixOtherValue(BilingualCorpus.TEST_CORPUS, true, backwardR[i], 0.0005, projectTestTime);
			align_uvf = models[0].posteriorAlignments(BilingualCorpus.TEST_CORPUS,
					forwardThresh,projectTestTime,true);
			align_uvb = models[1].posteriorAlignments(BilingualCorpus.TEST_CORPUS,
					backwardThresh,projectTestTime,true);
			
			System.out.println("Evaluating Size " + sizes[i] + "Forward Recall " + forwardR[i] + " Backward Recall " +  backwardR[i]) ;
			Evaluation evalForward = AlignmentEvaluator.evaluate(align_uvf,
					forwardCorpus.getGold());
			System.out.print("Forward ");
			AlignmentStats.printPhrases(align_uvf, false, false);
			System.out.println("Forward " + sizes[i ] + " " + evalForward.toString());
			System.out.println("Forward " + sizes[i ] + " " + evalForward.toSimpleString());
			Evaluation[] evalForwardBreak = AlignmentEvaluator.evaluateRareWords(align_uvf, forwardCorpus.getGold(), forwardCorpus);
			System.out.println("Forward Rare " + sizes[i ] + " " + evalForwardBreak[0]);
			System.out.println("Forward Rare " + sizes[i ] + " " +evalForwardBreak[0].toSimpleString());
			System.out.println("Forward Common " + sizes[i ] + " " +evalForwardBreak[1]);
			System.out.println("Forward Common " + sizes[i ] +  " " +  evalForwardBreak[1].toSimpleString());
			System.out.println("\n\n");
			
			Evaluation evalBackward = AlignmentEvaluator.evaluate(align_uvb,
					backwardCorpus.getGold());
			System.out.print("Backward ");
			AlignmentStats.printPhrases(align_uvb, false, false);
			System.out.println("Backward " + sizes[i ] + " " + evalBackward.toString());
			System.out.println("Backward " + sizes[i ] + " " + evalBackward.toSimpleString());
			Evaluation[] evalBackwardBreak = AlignmentEvaluator.evaluateRareWords(align_uvb, backwardCorpus.getGold(), backwardCorpus);
			System.out.println("Backward Rare :" + sizes[i ] + " " + evalBackwardBreak[0]);
			System.out.println("Backward Rare :" + sizes[i ] + " " + evalBackwardBreak[0].toSimpleString());
			System.out.println("Backward Common :" + sizes[i ] + " " + evalBackwardBreak[1]);
			System.out.println("Backward Common :" + sizes[i ] + " " + evalBackwardBreak[1].toSimpleString());
			System.out.println("\n\n");
			System.out.println("\n\n");
			
			oldSize = size;
		}
		
	}
}
